/**
 * XPT2046(AD芯片)
 * XPT2046 是一款 4 线制电阻式触摸屏控制器，内含 12 位分辨率 125KHz 转换速率逐步逼近型 A/D 转换器XPT2046 支持从 1.5V 到 5.25V 的低电压 I/0 接口。
 * XPT2046 能通过执行两次 A/D 转换查出被按的屏幕位置，余此之外，还可以测量加在触摸屏上的压力。
 * 内部自带 2.5V 参考电压，可以作为辅助输入、温度测量和电池监测之用，电池监测的电压范围可以从 OV 到 6V。
 * XPT2046 片内集成有一个温度传感器。
 * 在 2.7V 的典型工作状态下，关闭参考电压，功耗可小于 0.75mW。
 * XPT2046 采用微小的封装形式: TSSOP-16,QFN-16 和 VFBGA-48。
 * 工作温度范围为-40C~+85C。
 * 与 ADS7846、TSC2046、AK4182A 完全兼容
 */
#include <REGX52.H>

//片选段, 低电平有效
sbit AD_XPT2046_CS = P3^5;
//AD时钟
sbit AD_XPT2046_DCLK = P3^6;
//数据输入
sbit AD_XPT2046_DIN = P3^4;
//数据输出
sbit AD_XPT2046_DOUT = P3^7;

/**
 * 读AD, 需要输入命令字, 包括:
 *        S       : 起始位(第1位)，即 S 位。控制字的首位必须是 1，即S=1。在 XPT2046 的 DIN 引脚检测到起始位前，所有的输入将被忽略。
 *                  为 1表示一个新的控制字节到来，为0则忽略 PIN 引脚上数据
 * @param A2A1A0_Command A2,A1,A0: 地址位, 选择多路选择器的"现行通道"(见表 3、表 4和图 6)，触摸屏驱动和参考源输入。
 *                       AD_XPT2046_XP   测X+, XP(positive)
 *                       AD_XPT2046_YP   测Y
 *                       AD_XPT2046_VBAT 测VBAT(电池电压)
 *                       AD_XPT2046_AUX  测AUX
 * @param is_8bit_MODE MODE: 模式选择位，用于设置 ADC 的分辨率。
 *                       MODE=0，下一次的转换将是 12 位模式;
 *                       MODE=1，下一次的转换将是 8 位模式。
 * @param isSER        SER/DFR : 控制参考源模式，选择单端模式 (SER/DFR=1)，或者差分模式(SER/DFR=0)。
 *                      在X坐标、Y坐标和触摸压力测量中，为达到最佳性能，首选差分工作模式。参考电压来自开关驱动器的电压。
 *                      在单端模式下，转换器的参考电压固定为VREF相对于GND引脚的电压(更详细的说明，见表3和表4，图5 和图8)。
 * @param is_Open_Inner_Vref PDO, PD1: 表 5展示了掉电和内部参考电压配置的关系。("17.16.XPT2046内部参考电压.png")
 *                      ADC 的内部参考电压可以单独关团或者打开，但是，在转换前，需要额外的时间让内部参考电压稳定到最终稳定值;
 *                      如果内部参考源处于掉电状态，还要确保有足够的唤醒时间。ADC 要求是即时使用，无唤醒时间的。
 *                      另外还得注意，当 BUSY是高电平的时候，内部参考源禁止进入掉电模式。
 *                      XPT2046 的通道改变后，如果要关闭参考源，则要重新对XPT2046写入命令。
 *                      PD1: 是否打开内部参考电压源2.5V
 *                      低功率模式选择位。若为 11，器件总处于供电状态:若为00，器件在变换之间处于低功率模式
 * @param PD0          ?
 * @return 8位: 0~255
 *         12位: 0~65535
 */
unsigned int XPT2046_ReadAD(unsigned char A2A1A0_Command, bit is_8bit_MODE, bit isSER, bit is_Open_Inner_Vref, bit PD0) {
    unsigned char i;
    unsigned int ADValue = 0, divider = is_8bit_MODE ? 0x0800 : 0x8000;
    // A2A1A0_Command = A2A1A0_Command | (0 + is_8bit_MODE<<3) | (0 + isSER<<2) | (0 + is_Open_Inner_Vref<<1) | PD0;
    if (is_8bit_MODE) A2A1A0_Command |= 0x08;           if (isSER) A2A1A0_Command |= 0x04;
    if (is_Open_Inner_Vref) A2A1A0_Command |= 0x02;     if (PD0) A2A1A0_Command |= 0x01;
    //上升沿DIN输入
    AD_XPT2046_DCLK = 0;
    AD_XPT2046_CS = 0;
    for (i = 0; i < 8; i++) {
        AD_XPT2046_DIN = A2A1A0_Command & (0x80>>i);
        AD_XPT2046_DCLK = 1;
        AD_XPT2046_DCLK = 0;
    }
    //读1/2个字节 (8位, 或 12位: 低4位填充的0)
    for (i = 0; i < 12 - is_8bit_MODE * 4; i++) {
        //下降沿读出
        AD_XPT2046_DCLK = 1;
        AD_XPT2046_DCLK = 0;
        if (AD_XPT2046_DOUT) ADValue |= (divider>>i);
    }
    AD_XPT2046_CS = 1;
    return ADValue;
}
